/******************************************************************************
*	test2.c
*
*	coypright (C) 2009 Ding Lixing
*
******************************************************************************/
#include "vm.h"
#include "cm.h"
#include "uart.h"


static cmTASK t0, t1;
static vmSTACK s0[256], s1[256];

static cmSEM semFifo;
static cmSEM semPrio;
static cmMUTEX mutexCeil;
static cmMUTEX mutex;
static cmQUEUE queue;
static unsigned long queueBuf[10];
static cmCOND cond;

static void sleep(char *tName)
{
    uartPrintf("[%s]: sleep!\r\n", tName);
    cmTaskSleep(100);
    uartPrintf("[%s]: wakeup!\r\n", tName);
}

static void semGive(char *tName, char *objName, cmSEM *sem)
{
    uartPrintf("[%s]: give %s!\r\n", tName, objName);
    
    if(cmSemGive(sem) == 0){
        uartPrintf("[%s]: give %s ok!\r\n", tName, objName);
    }else{
        uartPrintf("[%s]: give %s fail!\r\n", tName, objName);
    }
}

static void semTake(char *tName, char *objName, cmSEM *sem)
{
    uartPrintf("[%s]: take %s!\r\n", tName, objName);
    if(cmSemTake(sem, CM_SLEEP_FOREVER) == 0){
        uartPrintf("[%s]: take %s ok!\r\n", tName, objName);
    }else{
        uartPrintf("[%s]: take %s fail!\r\n", tName, objName);
    }
}

static void mutexLock(char *tName, char *objName, cmMUTEX *mutex)
{
    uartPrintf("[%s]: take %s!\r\n", tName, objName);
    if(cmMutexLock(mutex, CM_SLEEP_FOREVER) == 0){
        uartPrintf("[%s]: take %s ok!\r\n", tName, objName);
    }else{
        uartPrintf("[%s]: take %s fail!\r\n", tName, objName);
    }
}

static void mutexUnlock(char *tName, char *objName, cmMUTEX *mutex)
{
    uartPrintf("[%s]: give %s!\r\n", tName, objName);
    
    if(cmMutexUnlock(mutex) >= 0){
        uartPrintf("[%s]: give %s ok!\r\n", tName, objName);
    }else{
        uartPrintf("[%s]: give %s fail!\r\n", tName, objName);
    }
}

static void queueSend(char *tName, char *objName, cmQUEUE *queue)
{
    unsigned long msg = 1234;
    uartPrintf("[%s]: send %s!\r\n", tName, objName);
    
    if(cmQueueSend(queue, msg, CM_SLEEP_FOREVER) == 0){
        uartPrintf("[%s]: send %s ok!\r\n", tName, objName);
    }else{
        uartPrintf("[%s]: send %s fail!\r\n", tName, objName);
    }
}

static void queueRecv(char *tName, char *objName, cmQUEUE *queue)
{
    unsigned long msg = 5678;
    uartPrintf("[%s]: recv %s!\r\n", tName, objName);
    
    if(cmQueueRecv(queue, &msg, CM_SLEEP_FOREVER) == 0){
        uartPrintf("[%s]: recv %s ok![%l]\r\n", tName, objName, msg);
    }else{
        uartPrintf("[%s]: recv %s fail!\r\n", tName, objName);
    }
}

static int condGetFlag(unsigned long *pflag)
{
    unsigned char s,e;
    
    uartPrintStr("input start bit:\r\n");
    while(uartRecvByte(&s));
    s = s - '0';
    uartPrintStr("input end bit:\r\n");
    while(uartRecvByte(&e));
    e = e - '0';
    if((s > e) || (e > (sizeof(unsigned long) * 8 - 1))){
        uartPrintStr("Error input!\r\n");
        return -1;
    }else{
        unsigned int i;
        unsigned long flag = 0;

        for(i = s; i <= e; i++){
            flag |= 1 << i;
        }
        *pflag = flag;
    }

    return 0;
}

static void condSet(char *tName, char *objName, cmCOND *cond)
{
    unsigned long flag;
        
    uartPrintf("[%s] set %s\r\n", tName, objName);
    if(condGetFlag(&flag) != 0){
        return;
    }
    if(cmCondSet(cond, flag) == 0){
        uartPrintf("[%s]: set %s (%x)ok!\r\n", tName, objName, flag);
    }else{
        uartPrintf("[%s]: set %s (%x)fail!\r\n", tName, objName, flag);
    }
}

static void condClr(char *tName, char *objName, cmCOND *cond)
{
    unsigned long flag;
        
    uartPrintf("[%s] clear %s\r\n", tName, objName);
    if(condGetFlag(&flag) != 0){
        return;
    }
    if(cmCondClr(cond, flag) == 0){
        uartPrintf("[%s]: clr %s (%x)ok!\r\n", tName, objName, flag);
    }else{
        uartPrintf("[%s]: clr %s (%x)fail!\r\n", tName, objName, flag);
    }
}

static void condWait(char *tName, char *objName, cmCOND *cond)
{
    unsigned long flag;
        
    
    if(condGetFlag(&flag) != 0){
        return;
    }
    uartPrintf("[%s] wait %s:%x\r\n", tName, objName, flag);

    if(cmCondWaitAll(cond, flag, CM_SLEEP_FOREVER) == 0){
        uartPrintf("[%s]: wait %s (%x)ok!\r\n", tName, objName, flag);
    }else{
        uartPrintf("[%s]: wait %s (%x)fail!\r\n", tName, objName, flag);
    }
}

static void condWaitClean(char *tName, char *objName, cmCOND *cond)
{
    unsigned long flag;
        
    if(condGetFlag(&flag) != 0){
        return;
    }
    uartPrintf("[%s] wait %s:%x\r\n", tName, objName, flag);

    if(cmCondWaitAllClean(cond, flag, CM_SLEEP_FOREVER) == 0){
        uartPrintf("[%s]: wait %s (%x)ok!\r\n", tName, objName, flag);
    }else{
        uartPrintf("[%s]: wait %s (%x)fail!\r\n", tName, objName, flag);
    }
}

static int testTask2(void *arg)
{
    char *tName = (char *)arg;

    for(;;){
        unsigned char ch;

        uartPrintf("%s>", tName);
        while(uartRecvByte(&ch) != 0);
        if(ch == 'i'){
            uartPrintf("hello!\r\n", tName);
        }else if(ch == 's'){
            sleep(tName);
        }else if(ch == 'q'){
            uartPrintf("[%s]: bye!\r\n", tName);
            break;
        }else if(ch == 't'){
            semTake(tName, "fifo sem",&semFifo);
        }else if(ch == 'T'){
            semTake(tName, "prio sem", &semPrio);
        }else if(ch == 'g'){
            semGive(tName, "fifo sem", &semFifo);
        }else if(ch == 'g'){
            semGive(tName, "prio sem", &semPrio);
        }else if(ch == 'l'){
            mutexLock(tName, "mutex", &mutex);
        }else if(ch == 'u'){
            mutexUnlock(tName, "mutex", &mutex);
        }else if(ch == 'L'){
            mutexLock(tName, "ceil mutex", &mutexCeil);
        }else if(ch == 'U'){
            mutexUnlock(tName, "ceil mutex", &mutexCeil);
        }else if(ch == 'S'){
            queueSend(tName, "queue", &queue);
        }else if(ch == 'R'){
            queueRecv(tName, "queue", &queue);
        }else if(ch == 'c'){
            condClr(tName, "cond", &cond);
        }else if(ch == 'b'){
            condSet(tName, "cond", &cond);
        }else if(ch == 'w'){
            condWait(tName, "cond", &cond);
        }else if(ch == 'W'){
            condWaitClean(tName, "cond", &cond);
        }else{
            uartPrintf("%s: %c\r\n", tName, ch);
        }
    }
    return 0;
}

void test2(void)
{
    uartPrintf("test 2\r\n");
    uartPrintf("\t[s]: sleep\r\n");
    uartPrintf("\t[q]: quit\r\n");
    uartPrintf("\t[i]: hello\r\n");
    uartPrintf("\t[t]: take fifo sem\r\n");
    uartPrintf("\t[T]: take prio sem\r\n");
    uartPrintf("\t[g]: give fifo sem\r\n");
    uartPrintf("\t[G]: give Prio sem\r\n");
    uartPrintf("\t[l]: lock mutex\r\n");
    uartPrintf("\t[L]: lock ceil mutex\r\n");
    uartPrintf("\t[u]: unlock mutex\r\n");
    uartPrintf("\t[U]: unlock ceil mutex\r\n");
    uartPrintf("\t[S]: send to queue\r\n");
    uartPrintf("\t[R]: recv from queue\r\n");
    uartPrintf("\t[c]: clr flag of cond\r\n");
    uartPrintf("\t[b]: set flag of cond\r\n");
    uartPrintf("\t[w]: wait flag of cond\r\n");
    uartPrintf("\t[W]: wait and clean flag of cond\r\n");
    
    cmSemInit(&semFifo, CM_OP_FIFO, 0, 1);
    cmSemInit(&semPrio, CM_OP_PRIO, 0, 1);

    cmMutexInit(&mutexCeil, CM_OP_FIFO | CM_OP_CEIL, 0);
    cmMutexInit(&mutex, CM_OP_PRIO, 0);

    cmQueueInit(&queue, CM_OP_PRIO, 10, queueBuf);

    cmCondInit(&cond, CM_OP_PRIO, 0);

    cmTaskInit(&t0, 1, 1, (void *)s0, sizeof(vmSTACK) * 256, testTask2, (void *)"t1_P1", 0);
    cmTaskInit(&t1, 1, 1, (void *)s1, sizeof(vmSTACK) * 256, testTask2, (void *)"t2_P1", 0);
    cmTaskStart(&t0);
    cmTaskStart(&t1);
}

